<?php
namespace app\api\model\food;

use think\facade\Cache;
use hema\Helper;
use hema\wechat\Driver;
use hema\wechat\Map;
use hema\delivery\Driver as Delivery;


/**
 * 购物车管理
 */
class Cart
{
    public $error = '';	//错误信息
    private $table_id;
    private $user_id;	//用户id
	private $shop_id;	//门店id
    private $applet_id;   //模板id
    private $cart = [];	//购物车列表
    private $clear = false;	//是否清空购物车

    /**
     * 构造方法
     */
    public function __construct($user_id, $shop_id, $applet_id,$table_id='')
    {
        $this->user_id = $user_id;
        $this->table_id = $table_id;
		$this->shop_id = $shop_id;
        $this->applet_id = $applet_id;
        if(empty($table_id)){
            $title = $user_id;
        }else{
            $title = $table_id;
        }
        $this->cart = Cache::get('cart_' . $title . '_' . $this->shop_id) ?: [];
    }
	
	 /**
     * 获取购物车内容
     */
    public function getCart()
    {
		return $this->cart;
	}

    public function getList($user, $order_mode = 0, $coupon_user_id = 0)
    {
        // 商品列表
        $goodsList = [];
        $goodsIds = array_unique(array_column($this->cart, 'goods_id'));
        foreach ((new Goods)->getListByIds($goodsIds) as $goods) {
            $goodsList[$goods['goods_id']] = $goods;
        }
        // 是否存在收货地址
        sizeof($user['address']) > 0 ? $exist_address = true : $exist_address = false;
        $pack_price = 0;//餐盒费
        // 购物车商品列表
        $cartList = [];
        foreach ($this->cart as $key => $cart) {
            // 判断商品不存在则自动删除
            if (!isset($goodsList[$cart['goods_id']])) {
                $this->delete($cart['goods_id'], $cart['goods_sku_id']);
                continue;
            }
            $goods = clone $goodsList[$cart['goods_id']];
            // 商品sku信息
            $goods['goods_sku_id'] = $cart['goods_sku_id'];
            // 商品sku不存在则自动删除
            if (!$goods['goods_sku'] = $goods->getGoodsSku($cart['goods_sku_id'])) {
                $this->delete($cart['goods_id'], $cart['goods_sku_id']);
                continue;
            }
            // 判断商品是否下架
            if ($goods['goods_status']['value'] != 10) {
                $this->setError('很抱歉，商品 [' . $goods['goods_name'] . '] 已下架');
            }
            //计算餐盒费
			if($order_mode == 20 OR $order_mode == 30){
				if($goods['pack_price']>0){
					$pack_price = $pack_price + $goods['pack_price']*$cart['goods_num'];
				}
			}
			// 商品单价
			$goods['goods_price'] = $goods['goods_sku']['goods_price'];
			// 商品总价
			$goods['total_num'] = $cart['goods_num'];
			$goods['total_price'] = $total_price = bcmul($goods['goods_price'], $cart['goods_num'], 2);
            $cartList[] = $goods->hidden(['category', 'content', 'spec']);
        }
        // 商品总金额
        $orderTotalPrice = Helper::getArrayColumnSum($cartList, 'total_price');
	    $order_pay_price = $orderTotalPrice;
		// 订单配送费用
        $expressPrice = 0;
		$min_price = 0;
		//餐盒费加入总价
		if($pack_price>0){
			$order_pay_price = $order_pay_price + $pack_price;
		}
		// 商品是否在配送范围
        $intraRegion = true;
		//如果是外卖 +配送费用
		//获取配送设置
        $delivery = Setting::getItem('delivery');
		if($order_mode==20){
			if($user['address_default']){
				//如果免费派送范围大于0
				$shop = Shop::get($this->shop_id);
				$map = new Map;
				//计算距离
				if($result = $map->getDistance($shop['coordinate'],$user['address_default']['location'])){
					$distance = $result[0]['distance'];//获取距离计算结果
					if($delivery['delivery_range'] < $distance){
						$this->setError('超出派送范围！');
                        $intraRegion = false;
					}else{
					    //如果超出免费区域就计算配送费
    					if($delivery['free_range'] < $distance){
    					    //判断是否开启自动配送
            				if($shop['is_delivery']['value'] == 1 AND $shop['delivery'] != 'self'){
            				    //如第三方配送，同步第三方配送费
            				    $dv = new Delivery($shop['delivery']);
            				    if($shop['delivery'] == 'uu'){
            				        $user_location = explode(',',$user['address_default']['location']);//拆分收货人定位经纬度
            		                $shop_location = explode(',',$shop['coordinate']);//拆分门店定位经纬度
            		                $post_data = [
                            			'origin_id' => order_no(),//第三方对接平台订单id
                            			'from_address' => $shop['address'],//起始地址
                            			'to_address' => $user['address_default']['detail'],//目的地址
                            			'city_name' => $shop['city'],//订单所在城市名 称(如郑州市就填”郑州市“，必须带上“市”)
                            			'county_name' => $shop['district'],//订单所在县级地名称(如金水区就填“金水区”)(可为空)
                            			'to_lat' => $user_location[0],//目的地坐标纬度，如果无，传0(坐标系为百度地图坐标系)
                            			'to_lng' => $user_location[1],//目的地坐标经度，如果无，传0(坐标系为百度地图坐标系)
                            			'from_lat' => $shop_location[0],//起始地坐标纬度，如果无，传0(坐标系为百度地图坐标系)
                            			'from_lng' => $shop_location[1] //起始地坐标经度，如果无，传0(坐标系为百度地图坐标系)	
                            		];
            				    }
            				    if($shop['delivery'] == 'dada'){
            				        $user_location = explode(',',$user['address_default']['location']);//拆分收货人定位经纬度
            		                $shop_location = explode(',',$shop['coordinate']);//拆分门店定位经纬度
            		                $city_code = $dv->getCiytCode($shop['city']);
            		                $post_data = [
                            			'shop_no' => $shop['dada_shop_id'],//是 门店编号
                            			'origin_id' => order_no(),//是 第三方订单ID
                            			'city_code' => $city_code,//是 订单所在城市的code
                            			'cargo_price' => 1,//是 订单金额
                            			'is_prepay' => 0,//是否需要垫付 1:是 0:否 (垫付订单金额，非运费)
                            			'receiver_name' => $user['address_default']['name'],//是 收货人姓名
                            			'receiver_address' => $user['address_default']['detail'],//是 收货人地址
                            			'callback' => base_url() . 'api/food.delivery/dada',//是 回调URL
                            			'receiver_lat' => $user_location[0], //否 收货人地址纬度
                            			'receiver_lng' => $user_location[1],//否 收货人地址经度
                            			'cargo_weight' => 0.1,//是	订单重量（单位：Kg）
                            		];
            				    }
            				    if($shop['delivery'] == 'make'){
            				        $post_data = [
                            			'fromcoord' => $shop['coordinate'],//起点地址坐标
                                        'tocoord' => $user['address_default']['location'],//终点地址坐标
                                        'shop_id' => $shop['make_shop_id'] //店铺ID	
                            		];
            				    }
            				    if($shop['delivery'] == 'sf'){
            				        $user_location = explode(',',$user['address_default']['location']);//拆分收货人定位经纬度
            		                $shop_location = explode(',',$shop['coordinate']);//拆分门店定位经纬度
                            		$post_data = [
                            			'shop_id' => $shop['sf_shop_id'],//$this->shop_id,//店铺ID
                            			//'shop_type' => 1,//店铺ID类型	1:顺丰店铺ID 2:接入方店铺ID
                            			'user_lng' => $user_location[1],//用户地址经度
                            			'user_lat' => $user_location[0],//用户地址纬度
                            			'user_address' => $user['address_default']['district'].','.$user['address_default']['detail'],//用户详细地址
                            			'city_name' => $user['address_default']['city'],//发单城市
                            			'weight' => 0,//物品重量（单位：克）
                            			'product_type' => 1, //物品类型，测试店铺请填写1，否则会造成【没有匹配的计价规则或计价规则已失效】
                            			'is_appoint' => 0,//是否是预约单0：非预约单；1：预约单
                            			'expect_time' => time()+1800,//期望送达时间,预约单需必传	秒级时间戳
                            			//'expect_pickup_time' => time()+600,//期望取货时间
                            			'lbs_type' => 2,//坐标类型，1：百度坐标，2：高德坐标
                            			'pay_type' => 1,//用户支付方式：1、已支付 0、货到付款
                            			'receive_user_money' => 0,//代收金额，单位：分
                            			'is_insured' => 0,//是否保价，0：非保价；1：保价
                            			'is_person_direct' => 0,//是否是专人直送订单，0：否；1：是
                            			'declared_value' => 0,//保价金额，单位：分
                            			'gratuity_fee' => 0,//订单小费，不传或者传0为不加小费	单位分，加小费最低不能少于100分
                            			'rider_pick_method' => 1,//物流流向	1：从门店取件送至用户 2：从用户取件送至门店
                            			'return_flag' => 511,//1:商品总价格，2:配送距离，4:物品重量，8:起送时间，16:期望送达时间，32:支付费用，64:实际支持金额，128:优惠卷总金额，256:结算方式,例如全部返回为填入511
                            			'push_time' => time(),
                            			//发货店铺信息；Obj,平台级开发者需要传入
                            			'shop' => [
                            				'shop_name' => $shop['shop_name'],//店铺名称
                            				'shop_phone' => $shop['phone'],//店铺电话
                            				'shop_address' => $shop['address'],//店铺地址
                            				'shop_lng' => $shop_location[1],//店铺经度
                            				'shop_lat' => $shop_location[0]//店铺纬度		
                            			]
                            		];
            				    }
                        		if($result = $dv->preOrder($post_data)){
                        		    $expressPrice = $result['price'];//第三方配送费
                                }else{
                                    $this->setError($dv->getError());
                                    return false;
                                }
            				}else{
        						$expressPrice = $delivery['delivery_price'];
        				    }
        				    $order_pay_price = $order_pay_price + $expressPrice;
    					}
					}
				}else{//定位错误
					$this->setError($map->getError());
				}
			}			
		}
		//计算最低配送价格范围
		if($orderTotalPrice<$delivery['min_price']){
			$min_price = $delivery['min_price'] - $orderTotalPrice;					
		}

        $order = [
            'coupon_list' => [], //优惠券列表
            'goods_list' => $cartList,                       // 商品列表
            'order_total_num' => $this->getTotalNum(),       // 商品总数量
            'order_total_price' => Helper::number2($orderTotalPrice),              // 商品总金额 (不含运费)
            'order_pay_price' => Helper::number2($order_pay_price),    // 实际支付金额
			'activity_price' => Helper::number2(0),	// 优惠金额
			'min_price' => $min_price,	// 起送价价
			'pack_price' => Helper::number2($pack_price),	// 餐盒费用
            'address' => $user['address_default'],  // 默认地址
            'exist_address' => $exist_address,      // 是否存在收货地址
            'express_price' => Helper::number2($expressPrice),       // 配送费用
            'intra_region' => $intraRegion,         // 当前用户收货城市是否存在配送规则中
            'has_error' => $this->hasError(),
            'error_msg' => $this->getError(),
        ];
        //获取优惠券列表
        $coupon_type = 0;
        $order_mode != 20 && $coupon_type = 10;
        $coupon_list = (new CouponUser)->getList($this->user_id,$coupon_type,$this->shop_id);
        if($coupon_list){
            $order = $this->checkCoupon($coupon_list,$order);
        }
        if($coupon_list AND $coupon_user_id > 0){
            $coupon = CouponUser::get($coupon_user_id,['coupon']);
            $order = $this->useCoupon($coupon,$order);
        }
        //如果是内部员工
        if($user['is_staff']['value'] == 1){
            $other = Setting::getItem('other');
            if($other['staff_price'] > 0){
                //计算员工折扣
                $price = $order['order_pay_price'] * (int)$other['staff_price'] / 100; //员工折扣后的价格；
                $order['activity_price'] = Helper::number2($order['activity_price']+$order['order_pay_price']-$price);
                $order['order_pay_price'] = Helper::number2($price);
            }
        }
        return $order;        
    }

    /**
     * 使用优惠券
     */
    private function useCoupon($coupon,$order)
    {
        //现金券验证
        if($coupon['type']['value'] == 10){
            //1立减 ={money=金额}
            //2首单减 = {money=金额}
            $price = (float)$coupon['coupon']['values']['money'];
            $order['order_pay_price'] = Helper::number2($order['order_pay_price'] - $price);// 实际支付金额
            $order['activity_price'] = Helper::number2($price); // 优惠金额
        }
        //折扣券
        if($coupon['type']['value'] == 20){
            //6等级折扣 ={ lv=等级 0不限,discount = 折扣 }
            $price = $order['order_total_price'] - $order['order_total_price'] * (float)$coupon['coupon']['values']['discount'] / 100; //计算优惠金额
            $order['order_pay_price'] = Helper::number2($order['order_pay_price'] - $price);// 实际支付金额
            $order['activity_price'] = Helper::number2($price); // 优惠金额
        }
        //满赠券
        if($coupon['type']['value'] == 30){
            //3满赠 = { condition=满足数值条件 {10金额 20数量} num = 数值 type = 赠品类型 {10优惠券 20商品} gift = 礼物{ id=编号 name=名称 image=图片 }
            $order['gift'] = $coupon['coupon']['values']['gift'];
        }
        //减免券
        if($coupon['type']['value'] == 40){
            //4满减 = { condition=满足数值条件 {10金额 20数量} num = 数量值 money = 减/折数值 } 
            //5满折 = { condition=满足数值条件 {10金额 20数量} num = 数量值 money = 减/折数值 } 
            if($coupon['coupon']['values']['condition'] == 10){
                //按照订单总金额
                if($coupon['coupon']['mode'] == 4){
                    //满减
                    $price = (float)$coupon['coupon']['values']['money']; //计算优惠金额
                }else{
                    //满折
                    $price = $order['order_total_price'] - $order['order_total_price'] * (float)$coupon['coupon']['values']['money'] / 100; //计算优惠金额
                }
                $order['order_pay_price'] = Helper::number2($order['order_pay_price'] - $price);// 实际支付金额
                $order['activity_price'] = Helper::number2($price); // 优惠金额
            }else{
                for($x=0;$x<sizeof($order['goods_list']);$x++){
                    //按照数量
                    if($order['goods_list'][$x]['total_num'] >= $coupon['coupon']['values']['num']){
                        if($coupon['coupon']['mode'] == 4){
                            //满减
                            $price = (float)$coupon['coupon']['values']['money']; //计算优惠金额
                            $order['goods_list'][$x]['active'] = '满减';
                        }else{
                            //满折
                            $price = $order['goods_list'][$x]['goods_sku']['goods_price'] - $order['goods_list'][$x]['goods_sku']['goods_price'] * (float)$coupon['coupon']['values']['money'] / 100; //计算优惠金额
                            $order['goods_list'][$x]['active'] = '满折';
                        }
                        $order['order_pay_price'] = Helper::number2($order['order_pay_price'] - $price);// 实际支付金额
                        $order['activity_price'] = Helper::number2($price); // 优惠金额
                        break;
                    }
                }
            }
        }
        if($order['order_pay_price'] < 0){
            $order['order_pay_price'] = Helper::number2(0);
        }
        return $order;
    }

    /**
     * 验证优惠券是否可用
     */
    private function checkCoupon($list,$order)
    {
        $coupon_list = [];
        for($n=0;$n<sizeof($list);$n++){
            $item = $list[$n]->toArray();
            unset($item['user']);
            //现金券验证
            if($item['type']['value'] == 10){
                //1立减 ={money=金额}
                if($item['coupon']['mode'] == 1){
                    array_push($coupon_list,$item);
                }
                //2首单减 = {money=金额}
                if($item['coupon']['mode'] == 2){
                    $orderCount = (new Order)->where(['user_id' => $this->user_id])->count();
                    if($orderCount == 0){
                        array_push($coupon_list,$item);
                    }
                }
            }
            //折扣券
            if($item['type']['value'] == 20){
                //6等级折扣 ={ lv=等级 0不限,discount = 折扣 }
                if($item['coupon']['values']['lv'] == 0){
                    array_push($coupon_list,$item);
                }else{
                    //获取用户详情
                    $user = UserModel::get($this->user_id);
                    if($user['v'] == $item['coupon']['values']['lv']){
                        array_push($coupon_list,$item);
                    }
                }
            }
            //满赠券
            if($item['type']['value'] == 30){
                //3满赠 = { condition=满足数值条件 {10金额 20数量} num = 数值 type = 赠品类型 {10优惠券 20商品} gift = 礼物{ id=编号 name=名称 image=图片 }
                if($item['coupon']['values']['condition'] == 10){
                    //按照金额
                    if($order['order_total_price'] >= $item['coupon']['values']['num']){
                        array_push($coupon_list,$item);
                    }
                }else{
                    //按照数量
                    if($order['order_total_num'] >= $item['coupon']['values']['num']){
                        array_push($coupon_list,$item);
                    }
                }
            }
            //减免券
            if($item['type']['value'] == 40){
                //4满减 = { condition=满足数值条件 {10金额 20数量} num = 数量值 money = 减/折数值 } 
                //5满折 = { condition=满足数值条件 {10金额 20数量} num = 数量值 money = 减/折数值 } 
                if($item['coupon']['values']['condition'] == 10){
                    //按照订单总金额
                    if($order['order_total_price'] >= $item['coupon']['values']['num']){
                        array_push($coupon_list,$item);
                    }
                }else{
                    foreach ($order['goods_list'] as $vo) {
                        //按照单品数量
                        if($vo['total_num'] >= $item['coupon']['values']['num']){
                            array_push($coupon_list,$item);
                            break;
                        }
                    }
                }
            }
        }
        $order['coupon_list'] = $coupon_list;
        return $order;
    }

    /**
     * 添加购物车
     */
    public function add($data)
    {
        // 购物车商品索引
        $index = $data['goods_id'] . '_' . $data['goods_sku_id'];
        // 商品信息
        $goods = Goods::detail($data['goods_id']);
        // 商品sku信息
        $goods['goods_sku'] = $goods->getGoodsSku($data['goods_sku_id']);
        // 判断商品是否下架
        if ($goods['goods_status']['value'] != 10) {
            $this->setError('很抱歉，该商品已下架');
            return false;
        }
        // 判断商品库存
        $cartGoodsNum = $data['goods_num'] + (isset($this->cart[$index]) ? $this->cart[$index]['goods_num'] : 0);
        $data['create_time'] = time();
        if (sizeof($this->cart) == 0) {
            $this->cart[$index] = $data;
            return true;
        }
        isset($this->cart[$index]) ? $this->cart[$index]['goods_num'] = $cartGoodsNum : $this->cart[$index] = $data;
        return true;
    }

    /**
     * 减少购物车中某商品数量
     */
    public function sub($data)
    {
        $index = $data['goods_id'] . '_' . $data['goods_sku_id'];
        if($this->cart[$index]['goods_num'] > 1 ){
            $this->cart[$index]['goods_num']--;
        }elseif($this->cart[$index]['goods_num'] == 1){
            unset($this->cart[$index]);
        }
    }

    /**
     * 删除购物车中指定商品
     */
    public function delete($data)
    {
        //为空是商城批量删除
        if(empty($data['goods_id'])){
            $indexArr = strpos( $data['goods_sku_id'], ',') !== false ? explode(',',  $data['goods_sku_id']) : [ $data['goods_sku_id']];
            foreach ($indexArr as $index) {
                if (isset($this->cart[$index])) unset($this->cart[$index]);
            }
        }else{
            $index = $data['goods_id'] . '_' . $data['goods_sku_id'];
            if (isset($this->cart[$index])) unset($this->cart[$index]);
        }
    }

    /**
     * 获取当前用户购物车商品总数量
     */
    public function getTotalNum()
    {
        return array_sum(array_column($this->cart, 'goods_num'));
    }

    /**
     * 析构方法
     * 将cart数据保存到缓存文件
     */
    public function __destruct()
    {
        if(empty($this->table_id)){
            $title = $this->user_id;
        }else{
            $title = $this->table_id;
        }
        $this->clear !== true && Cache::set('cart_' . $title . '_' . $this->shop_id, $this->cart, 86400);
    }

    /**
     * 清空当前用户购物车
     */
    public function clearAll()
    {
        $this->clear = true;
        if(empty($this->table_id)){
            $title = $this->user_id;
        }else{
            $title = $this->table_id;
        }
        Cache::delete('cart_' . $title . '_' . $this->shop_id);
    }

    /**
     * 设置错误信息
     */
    private function setError($error)
    {
        empty($this->error) && $this->error = $error;
    }

    /**
     * 是否存在错误
     */
    private function hasError()
    {
        return !empty($this->error);
    }

    /**
     * 获取错误信息
     */
    public function getError()
    {
        return $this->error;
    }

}
